home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / editor / j414src.arc / IPROCXPT.C < prev    next >
C/C++ Source or Header  |  1989-10-10  |  8KB  |  400 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. /* NOTE WELL:
  9.  * This file is "included" into iproc.c -- it is not compiled separately!
  10.  */
  11.  
  12. #include <sys/time.h>
  13. #include <fcntl.h>
  14. #include <signal.h>
  15. #include <sgtty.h>
  16. #include <errno.h>
  17. #include "wait.h"
  18.  
  19. #define DEAD    1    /* dead but haven't informed user yet */
  20. #define STOPPED    2    /* job stopped */
  21. #define RUNNING    3    /* just running */
  22. #define NEW    4    /* brand new, never been ... received no input */
  23.  
  24. /* If process is dead, flags says how. */
  25. #define EXITED    1
  26. #define KILLED    2
  27.  
  28. #define isdead(p)    ((p) == NULL || proc_state((p)) == DEAD || (p)->p_fd == -1)
  29. #define makedead(p)    { proc_state((p)) = DEAD; }
  30.  
  31. #define proc_buf(p)    ((p)->p_buffer->b_name)
  32. #define proc_cmd(p)    ((p)->p_name)
  33. #define proc_state(p)    ((p)->p_state)
  34.  
  35. private Process    *procs = 0;
  36.  
  37. long    global_fd = 1;
  38. int    NumProcs = 0;
  39.  
  40. #include "ttystate.h"
  41.  
  42. private Process *
  43. proc_pid(pid)
  44. int    pid;
  45. {
  46.     register Process    *p;
  47.  
  48.     for (p = procs; p != 0; p = p->p_next)
  49.         if (p->p_pid == pid)
  50.             break;
  51.  
  52.     return p;
  53. }
  54.  
  55. void
  56. read_proc(fd)
  57. register int    fd;
  58. {
  59.     register Process    *p;
  60.     int    n;
  61.     char    ibuf[1024];
  62.  
  63.     for (p = procs; p != 0; p = p->p_next)
  64.         if (p->p_fd == fd)
  65.             break;
  66.  
  67.     if (p == 0) {
  68.         writef("\riproc: unknown fd %d", fd);
  69.         return;
  70.     }
  71.  
  72.     n = read(fd, ibuf, sizeof(ibuf) - 1);
  73.     if (n == -1 && (errno == EIO || errno == EWOULDBLOCK)) {
  74.         if (proc_state(p) == NEW)
  75.             return;
  76.         proc_close(p);
  77.         makedead(p);
  78.         return;
  79.     } else {
  80.         if (proc_state(p) != RUNNING) {
  81.             proc_state(p) = RUNNING;
  82.             UpdModLine = YES;
  83.         }
  84.     }
  85.     if (n <= 0) {
  86.         if (n == 0)
  87.             strcpy(ibuf, "[Process EOF]");
  88.         else
  89.             swritef(ibuf, "\n[pty read error: %d]\n", errno);
  90.     } else
  91.         ibuf[n] = '\0';
  92.     proc_rec(p, ibuf);
  93. }
  94.  
  95. void
  96. ProcKill()
  97. {
  98.     register Buffer    *b;
  99.     char    *bname;
  100.  
  101.     bname = ask_buf(curbuf);
  102.  
  103.     if ((b = buf_exists(bname)) == 0)
  104.         complain("[No such buffer]");
  105.     if (b->b_process == 0)
  106.         complain("%s not tied to a process.", bname);
  107.     proc_kill(b->b_process, SIGKILL);
  108. }
  109.  
  110. void
  111. ProcCont()
  112. {
  113.     Process    *p;
  114.  
  115.     if ((p = curbuf->b_process) == 0)
  116.         complain("[No process]");
  117.     if (p->p_state != DEAD) {
  118.         proc_kill(p, SIGCONT);
  119.         UpdModLine = YES;
  120.         p->p_state = RUNNING;
  121.     }
  122. }
  123.  
  124. private void
  125. send_p(c)
  126. char    c;
  127. {
  128.     Process    *p;
  129.     char    buf[2];
  130.  
  131.     if ((p = curbuf->b_process) == 0)
  132.         complain("[No process]");
  133.     ToLast();
  134.     buf[0] = c;
  135.     buf[1] = '\0';
  136.     proc_rec(p, buf);
  137.     (void) write(p->p_fd, &c, (size_t) 1);
  138. }
  139.  
  140. void
  141. ProcEof()
  142. {
  143.     send_p(tc[OFF].t_eofc);
  144. }
  145.  
  146. void
  147. ProcInt()
  148. {
  149.     send_p(tc[OFF].t_intrc);
  150. }
  151.  
  152. void
  153. ProcQuit()
  154. {
  155.     send_p(tc[OFF].t_quitc);
  156. }
  157.  
  158. void
  159. ProcStop()
  160. {
  161.     send_p(ls[OFF].t_suspc);
  162. }
  163.  
  164. void
  165. ProcDStop()
  166. {
  167.     send_p(ls[OFF].t_dsuspc);
  168. }
  169.  
  170. private void
  171. proc_close(p)
  172. Process *p;
  173. {
  174.     SigHold(SIGCHLD);    /* be mutually exclusive */
  175.  
  176.     if (p->p_fd >= 0) {
  177.         (void) close(p->p_fd);
  178.         global_fd &= ~(1L << p->p_fd);
  179.         NumProcs -= 1;
  180.         p->p_fd = -1;
  181.     }
  182.  
  183.     SigRelse(SIGCHLD);
  184. }
  185.  
  186. private void
  187. proc_write(p, buf, nbytes)
  188. Process *p;
  189. char    *buf;
  190. size_t    nbytes;
  191. {
  192.     long    mask = (1 << p->p_fd);
  193.  
  194.     while (write(p->p_fd, buf, nbytes) <  0)
  195.         select(p->p_fd + 1, (long *) 0, &mask, (long *) 0, (struct timeval *) 0);
  196. }
  197.  
  198. #ifdef    STDARGS
  199.     private void
  200. proc_strt(char *bufname, int clobber, ...)
  201. #else
  202.     private /*VARARGS2*/ void
  203. proc_strt(bufname, clobber, va_alist)
  204.     char    *bufname;
  205.     int    clobber;
  206.     va_dcl
  207. #endif
  208. {
  209.     va_list    ap;
  210.     char    *argv[32],
  211.         *cp;
  212.     Window *owind = curwind;
  213.     int    pid;
  214.     Process    *newp;
  215.     Buffer     *newbuf;
  216.     int    i,
  217.         ptyfd,
  218.         ttyfd,
  219.         ldisc,
  220.         lmode;
  221.     register char    *s,
  222.             *t;
  223.     char    ttybuf[11],
  224.         ptybuf[11];
  225.     char    cmdbuf[128];
  226. #ifdef BRLUNIX
  227.     struct sg_brl sgt;
  228. #else
  229.     struct sgttyb sgt;
  230. #endif
  231.  
  232. #ifdef TIOCGWINSZ
  233.     struct winsize win;
  234. #else
  235. #  ifdef BTL_BLIT
  236. #  include <sys/jioctl.h>
  237.     struct jwinsize jwin;
  238. #  endif
  239. #endif
  240.  
  241.     isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  242.                    or is of type B_PROCESS */
  243.     for (s = "pqrs"; *s; s++) {
  244.         for (t = "0123456789abcdef"; *t; t++) {
  245.             swritef(ptybuf, "/dev/pty%c%c", *s, *t);
  246.             if ((ptyfd = open(ptybuf, 2)) >= 0) {
  247.                 strcpy(ttybuf, ptybuf);
  248.                 ttybuf[5] = 't';
  249.                 /* make sure both ends are available */
  250.                 if ((i = open(ttybuf, 2)) < 0)
  251.                     continue;
  252.                 (void) close(i);
  253.                 goto out;
  254.             }
  255.         }
  256.     }
  257.  
  258. out:    if (s == 0 && t == 0)
  259.         complain("[Out of ptys!]");
  260.  
  261. #ifdef TIOCGETD
  262.     (void) ioctl(0, TIOCGETD, (UnivPtr) &ldisc);
  263. #endif
  264. #ifdef TIOCLGET
  265.     (void) ioctl(0, TIOCLGET, (UnivPtr) &lmode);
  266. #endif
  267. #ifdef TIOCGWINSZ
  268.     (void) ioctl(0, TIOCGWINSZ, (UnivPtr) &win);
  269. #else
  270. #  ifdef BTL_BLIT
  271.     (void) ioctl(0, JWINSIZE, (UnivPtr) &jwin);
  272. #  endif /* BTL_BLIT */
  273. #endif
  274.  
  275.     SigHold(SIGCHLD);
  276. #ifdef SIGWINCH
  277.     SigHold(SIGWINCH);
  278. #endif
  279.     switch (pid = fork()) {
  280.     case -1:
  281.         (void) close(ptyfd);
  282.         message("[Fork failed!]");
  283.         goto fail;
  284.  
  285.     case 0:
  286.         SigRelse(SIGCHLD);
  287. #ifdef SIGWINCH
  288.         SigRelse(SIGWINCH);
  289. #endif
  290.         for (i = 0; i < 32; i++)
  291.             (void) close(i);
  292.  
  293. #ifdef TIOCNOTTY
  294.         if ((i = open("/dev/tty", 2)) >= 0) {
  295.             (void) ioctl(i, TIOCNOTTY, (UnivPtr) 0);
  296.             (void) close(i);
  297.         }
  298. #endif
  299.         if ((ttyfd = open(ttybuf, 2)) < 0)
  300.             exit(-1);
  301.         (void) dup2(ttyfd, 1);
  302.         (void) dup2(ttyfd, 2);
  303.  
  304. #ifdef TIOCSETD
  305.         (void) ioctl(0, TIOCSETD, (UnivPtr) &ldisc);
  306. #endif
  307. #ifdef TIOCLSET
  308.         (void) ioctl(0, TIOCLSET, (UnivPtr) &lmode);
  309. #endif
  310. #ifdef TIOCSETC
  311.         (void) ioctl(0, TIOCSETC, (UnivPtr) &tc[OFF]);
  312. #endif
  313. #ifdef TIOCSLTC
  314.         (void) ioctl(0, TIOCSLTC, (UnivPtr) &ls[OFF]);
  315. #endif
  316.  
  317. #ifdef TIOCGWINSZ
  318. #    ifdef SIGWINCH
  319.         (void) signal(SIGWINCH, SIG_IGN);
  320. #    endif
  321.         win.ws_row = curwind->w_height;
  322.         (void) ioctl(0, TIOCSWINSZ, (UnivPtr) &win);
  323. #else
  324. #  ifdef BTL_BLIT
  325.         jwin.bytesy = curwind->w_height;
  326.         (void) ioctl(0, JSWINSIZE, (UnivPtr) &jwin);
  327. #  endif
  328. #endif
  329.  
  330.         sgt = sg[OFF];
  331.         sgt.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
  332.         (void) stty(0, &sgt);
  333.  
  334.         {
  335.             int    on = 1;
  336.  
  337.             (void) ioctl(0, TIOCREMOTE, (UnivPtr) &on);
  338.         }
  339.  
  340.         i = getpid();
  341.         (void) ioctl(0, TIOCSPGRP, (UnivPtr) &i);
  342.         (void) setpgrp(0, i);
  343.         va_init(ap, clobber);
  344.         make_argv(argv, ap);
  345.         va_end(ap);
  346.         execv(argv[0], (const char **) &argv[1]);
  347.         (void) write(1, "execve failed!\n", (size_t) 15);
  348.         _exit(errno + 1);
  349.     }
  350.  
  351.     newp = (Process *) emalloc(sizeof *newp);
  352.  
  353. #ifdef O_NDELAY
  354.     fcntl (ptyfd, F_SETFL, O_NDELAY);
  355. #endif
  356.     newp->p_fd = ptyfd;
  357.     newp->p_pid = pid;
  358.  
  359.     newbuf = do_select((Window *) 0, bufname);
  360.     newbuf->b_type = B_PROCESS;
  361.     newp->p_buffer = newbuf;
  362.     newbuf->b_process = newp;    /* sorta circular, eh? */
  363.     pop_wind(bufname, clobber, B_PROCESS);
  364.     /* Pop_wind() after everything is set up; important!
  365.        Bindings won't work right unless newbuf->b_process is already
  366.        set up BEFORE NEWBUF is first SetBuf()'d. */
  367.     ToLast();
  368.     if (!bolp())
  369.         LineInsert(1);
  370.  
  371.     cmdbuf[0] = '\0';
  372.     va_init(ap, clobber);
  373.     while ((cp = va_arg(ap, char *)) != NIL)
  374.         swritef(&cmdbuf[strlen(cmdbuf)], "%s ", cp++);
  375.     va_end(ap);
  376.  
  377.     newp->p_name = copystr(cmdbuf);
  378.     newp->p_state = NEW;
  379.     newp->p_reason = 0;
  380.     newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
  381.     newp->p_dbx_mode = NO;
  382.  
  383.     newp->p_next = procs;
  384.     procs = newp;
  385.     NumProcs += 1;
  386.     global_fd |= 1L << newp->p_fd;
  387.     SetWind(owind);
  388.  
  389. fail:    SigRelse(SIGCHLD);
  390. #ifdef SIGWINCH
  391.     SigRelse(SIGWINCH);
  392. #endif
  393. }
  394.  
  395. void
  396. pinit()
  397. {
  398.     (void) signal(SIGCHLD, proc_child);
  399. }
  400.